//
// * Copyright (c) 2002-2009 "Neo Technology,"
// *     Network Engine for Objects in Lund AB [http://neotechnology.com]
// *
// * This file is part of Neo4j.
// * 
// * Neo4j is free software: you can redistribute it and/or modify
// * it under the terms of the GNU Affero General Public License as
// * published by the Free Software Foundation, either version 3 of the
// * License, or (at your option) any later version.
// * 
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// * GNU Affero General Public License for more details.
// * 
// * You should have received a copy of the GNU Affero General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// 
namespace org.neo4j.kernel.impl.cache
{

	using Test = junit.framework.Test;
	using TestCase = junit.framework.TestCase;
	using TestSuite = junit.framework.TestSuite;

	using LruCache = org.neo4j.kernel.impl.cache.LruCache;

	public class TestLruCache : TestCase
	{
		public TestLruCache(string testName) : base(testName)
		{
		}

		static void Main(string[] args)
		{
			junit.textui.TestRunner.run(suite());
		}

		public static Test suite()
		{
			TestSuite suite = new TestSuite(typeof(TestLruCache));
			return suite;
		}

		public virtual void testCreate()
		{
			try
			{
				new LruCache<object, object>("TestCache", 0, null);
				fail("Illegal maxSize should throw exception");
			}
			catch (IllegalArgumentException e)
			{ // good
			}
			LruCache<object, object> cache = new LruCache<object, object>("TestCache", 70, null);
			try
			{
				cache.put(null, new object());
				fail("Null key should throw exception");
			}
			catch (IllegalArgumentException e)
			{ // good
			}
			try
			{
				cache.put(new object(), null);
				fail("Null element should throw exception");
			}
			catch (IllegalArgumentException e)
			{ // good
			}
			try
			{
				cache.get(null);
				fail("Null key should throw exception");
			}
			catch (IllegalArgumentException e)
			{ // good
			}
			try
			{
				cache.Remove(null);
				fail("Null key should throw exception");
			}
			catch (IllegalArgumentException e)
			{ // good
			}
			cache.put(new object(), new object());
			cache.Clear();
		}

		private class LruCacheTest<K, E> : LruCache<K, E>
		{
			private object cleanedElement = null;

			internal LruCacheTest(string name, int maxSize) : base(name, maxSize, null)
			{
			}

			public override void elementCleaned(E element)
			{
				cleanedElement = element;
			}

			internal virtual object getLastCleanedElement()
			{
				return cleanedElement;
			}
		}

		public virtual void testSimple()
		{
			LruCacheTest<object, object> cache = new LruCacheTest<object, object>("TestCache", 3);
			string s1 = new string("1");
			int key1 = new int(1);
			string s2 = new string("2");
			int key2 = new int(2);
			string s3 = new string("3");
			int key3 = new int(3);
			string s4 = new string("4");
			int key4 = new int(4);
			string s5 = new string("5");
			int key5 = new int(5);
			cache.put(key1, s1);
			cache.put(key2, s2);
			cache.put(key3, s3);
			cache.get(key2);
			assertEquals(null, cache.getLastCleanedElement());
			cache.put(key4, s4);
			assertEquals(s1, cache.getLastCleanedElement());
			cache.put(key5, s5);
			assertEquals(s3, cache.getLastCleanedElement());
			int size = cache.size();
			assertEquals(3, size);
			assertEquals(null, cache.get(key1));
			assertEquals(s2, cache.get(key2));
			assertEquals(null, cache.get(key3));
			assertEquals(s4, cache.get(key4));
			assertEquals(s5, cache.get(key5));
			cache.Clear();
			assertEquals(0, cache.size());
		}

		public virtual void testResize()
		{
			LruCacheTest<object, object> cache = new LruCacheTest<object, object>("TestCache", 3);
			string s1 = new string("1");
			int key1 = new int(1);
			string s2 = new string("2");
			int key2 = new int(2);
			string s3 = new string("3");
			int key3 = new int(3);
			string s4 = new string("4");
			int key4 = new int(4);
			string s5 = new string("5");
			int key5 = new int(5);
			cache.put(key1, s1);
			cache.put(key2, s2);
			cache.put(key3, s3);
			cache.get(key2);
			assertEquals(null, cache.getLastCleanedElement());
			assertEquals(cache.maxSize(), cache.size());
			cache.resize(5);
			assertEquals(5, cache.maxSize());
			assertEquals(3, cache.size());
			cache.put(key4, s4);
			assertEquals(null, cache.getLastCleanedElement());
			cache.put(key5, s5);
			assertEquals(null, cache.getLastCleanedElement());
			assertEquals(cache.maxSize(), cache.size());
			cache.resize(4);
			assertEquals(s1, cache.getLastCleanedElement());
			assertEquals(cache.maxSize(), cache.size());
			cache.resize(3);
			assertEquals(s3, cache.getLastCleanedElement());
			assertEquals(3, cache.maxSize());
			assertEquals(3, cache.size());
		}
	}
}